#include <GameEngine/Graphics/Scene/scene.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


//! Default constructor
Scene::Scene() {}

//! Copy constructor
/*!
 @param rhs The scene to copy
 */
Scene::Scene(const Scene& rhs) : scene_elements_(rhs.scene_elements_) {}

//! Assignment operator
/*!
 @param rhs The scene to copy
 @return A reference to this scene
 */
Scene& Scene::operator=(const Scene& rhs) {
	if ( &rhs != this ) {
		scene_elements_ = rhs.scene_elements_;
	}
	return *this;
}

//! Destructor
Scene::~Scene() {}

//! Prepare all the elements of the scene to be drawn
/*!
 @return True if all the elements of the scene were correctly prepared, false otherwise
 */
bool Scene::prepare_scene() {
	bool res = true;
	for ( int k = 0; k < (int)SceneElement::NumberElementTypes; ++k ) {
		SceneElement::ElementType type = (SceneElement::ElementType)k;
		for ( QList<SceneElement*>::const_iterator it = scene_elements_.begin(); it != scene_elements_.end(); ++it ) {
			const SceneElement& e = *(*it);
			if ( e.type() != type ) continue;
			res &= (*it)->prepare_draw();
		}
	}
	return res;
}

//! Draw all the elements of the scene
/*!
 @return True if all the elements of the scene were drawn, false otherwise
 */
bool Scene::draw_scene(const Line3d<float>& ray) {
	bool res = true;
	for ( int k = 0; k < (int)SceneElement::NumberElementTypes; ++k ) {
		SceneElement::ElementType type = (SceneElement::ElementType)k;
		for ( QList<SceneElement*>::const_iterator it = scene_elements_.begin(); it != scene_elements_.end(); ++it ) {
			const SceneElement& e = *(*it);
			if ( e.type() != type ) continue;
			res &= (*it)->draw(ray);
		}
	}
	return res;
}

//! Cleanup all the elements of the scene after they have been drawn
/*!
 @return True if all the elements of the scene were correctly cleaned up, false otherwise
 */
bool Scene::finish_scene() {
	bool res = true;
	for ( int k = 0; k < (int)SceneElement::NumberElementTypes; ++k ) {
		SceneElement::ElementType type = (SceneElement::ElementType)k;
		for ( QList<SceneElement*>::const_iterator it = scene_elements_.begin(); it != scene_elements_.end(); ++it ) {
			const SceneElement& e = *(*it);
			if ( e.type() != type ) continue;
			res &= (*it)->finish_draw();
		}
	}
	return res;
}

//! Add an element to the scene
/*!
 @param element The element to be added to the scene
 @param position The position of the element in the scene (i.e., the order in which the element
                 is drawn relatively to the other elements). If position is zero (or lower than
		         zero), the element is drawn first. If position is equal to the number of
		         elements in the scene (or greater than the number of elements in the scene), it
		         is drawn last
 @return True if element could be added, false otherwise. Element may not be added if it
         was already present in the scene
 */
bool Scene::add_element(SceneElement* element, int position) {
	// Check if the element already exists
	if ( find_element(element) == true ) return false;

	// Insert the element in the scene
	scene_elements_.insert(position, element);
	return true;
}

//! Remove an element from the scene
/*!
 @param element The element to be removed from the scene
 @return True if element could be removed, false otherwise. Element may not be removed if
         it was not present in the scene
 */
bool Scene::remove_element(SceneElement* element) {
	return ( scene_elements_.removeAll(element) > 0 );
}

//! Tries to locate an element in the scene
/*!
 @return True if element was present in the scene, false otherwise
 */
bool Scene::find_element(SceneElement* element) const {
	return ( scene_elements_.indexOf(element) >= 0 );
}

//! Accessor to the elements present in the scene
/*!
 @return A constant reference to the list of all the elements present in the scene
 */
const QList<SceneElement*>& Scene::scene_elements() const {
	return scene_elements_;
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
